package com.aplink.generic;

import java.io.File;
import java.util.Date;

import org.acra.ACRA;

import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.aplink.generic.cache.ContentDataManager;
import com.aplink.generic.cache.FormDesignManager;
import com.aplink.generic.cache.MasterConfigManager;
import com.aplink.generic.pojo.MainMenu;
import com.aplink.generic.pojo.MasterConfig;
import com.aplink.generic.sharepreference.GenericSharePreference;
import com.aplink.generic.util.LogUtil;
import com.aplink.generic.util.ResourcesHelper;
import com.aplink.generic.xmlpullparser.MainMenuXmlPullParser;

public abstract class GenericApplication extends Application {

	protected static GenericApplication instance;

	public static GenericApplication getInstance() {
		return instance;
	}

	private MainMenu mMainMenu;

	private void applicationUpgrade() {
		final int oldVersion = GenericSharePreference.getInstance()
		        .getAppVersion();
		try {
			final PackageInfo pInfo = getPackageManager().getPackageInfo(
			        getPackageName(), 0);
			final int appVerion = pInfo.versionCode;
			if (oldVersion == -1) {
				GenericSharePreference.getInstance().setAppVersion(appVerion);
			}
			if (oldVersion < appVerion) {
				onApplicationUpgrade(oldVersion, oldVersion);
			}
		} catch (final NameNotFoundException e) {
			e.printStackTrace();
		}
	}

	public void createLoginSession(final String username, final String token) {
		GenericSharePreference.getInstance().setUserlogin(username)
		        .setToken(token).setFirstStart(false);
	}

	public boolean deleteDirectory(final File directory) {
		if (directory.exists()) {
			final File[] files = directory.listFiles();
			if (null != files) {
				for (final File file : files) {
					if (file.isDirectory()) {
						deleteDirectory(file);
					} else {
						file.delete();
					}
				}
			}
		}
		return (directory.delete());
	}

	public ActivityInfo getActivityInfo(final String activityName)
	        throws NameNotFoundException {
		final String packageName = GenericApplication.getInstance()
		        .getApplicationContext().getPackageName();
		final ActivityInfo[] listActivity = GenericApplication.getInstance()
		        .getApplicationContext().getPackageManager()
		        .getPackageInfo(packageName, PackageManager.GET_ACTIVITIES).activities;
		for (final ActivityInfo activityInfo : listActivity) {
			String url = activityInfo.name.substring(0,
			        activityInfo.name.lastIndexOf("."));
			if (activityInfo.name.equalsIgnoreCase(url + "." + activityName)) {
				return activityInfo;
			}
		}
		return null;
	}

	public String getApplicationName() {
		final int applicationNameID = getApplicationContext()
		        .getApplicationInfo().labelRes;
		return getApplicationContext().getResources().getString(
		        applicationNameID);
	}

	protected abstract String getBarCodeLicence();

	public String getCreatedTime() {
		return String.format("%s.%s", getDeviceID(), new Date().getTime());
	}

	public String getDeviceID() {
		final TelephonyManager mngr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		if (TextUtils.isEmpty(mngr.getDeviceId())) {
			return mngr.getDeviceId();
		}
		return Secure.getString(getContentResolver(), Secure.ANDROID_ID);
	}

	public final MainMenu getMainMenu() {
		return this.mMainMenu;
	}

	public Class<?> getTargetActivity(final String activityName) {
		try {
			final ActivityInfo activityInfo = GenericApplication.getInstance()
			        .getActivityInfo(activityName);
			final Class<?> activityClass = Class.forName(activityInfo.name);
			return activityClass;
		} catch (NameNotFoundException | ClassNotFoundException
		        | NullPointerException e) {
			LogUtil.error("Are you forgot to declare for the activity "
			        + activityName, "getTargetActivity", getClass());
		}
		return null;
	}

	public int getVersionCode() {
		try {
			PackageInfo pInfo = getPackageManager().getPackageInfo(
			        getPackageName(), 0);
			return pInfo.versionCode;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return 1;
	}

	protected abstract int initMasterConfig();

	public boolean isNetworkAvailable() {
		final ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
		if ((networkInfo != null) && networkInfo.isConnected()) {
			return true;
		}
		return false;
	}

	public void logout(final GenericFragment genericFragment) {
		try {
			GenericSharePreference.getInstance().setLogined(false);
			final Context context = genericFragment.getApplicationContext();
			final ActivityInfo activityInfo = getActivityInfo(MasterConfigManager
			        .getInstance().get(initMasterConfig()).getLoginClass());
			final Class<?> activityClass = Class.forName(activityInfo.name);
			final Intent intent = new Intent(context, activityClass);
			intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			genericFragment.startActivity(intent);
		} catch (final NameNotFoundException e) {
			e.printStackTrace();
		} catch (final ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	protected abstract void onApplicationUpgrade(int oldVersion, int newVersion);

	@Override
	public void onCreate() {
		super.onCreate();
		ACRA.init(this);
		GenericApplication.instance = this;
		MasterConfig mMasterConfig = MasterConfigManager.getInstance().get(
		        initMasterConfig());
		GenericSharePreference.getInstance().setMasterConfigFileID(
		        initMasterConfig());
		applicationUpgrade();
		if (mMasterConfig.getMainMenuID() != ResourcesHelper.RESOURCE_NOT_FOUND) {
			this.mMainMenu = MainMenuXmlPullParser.parse(
			        mMasterConfig.getMainMenuID(), getApplicationContext());
		}
	}

	public void resetApplication(final GenericFragment genericFragment) {
		final String databaseName = MasterConfigManager.getInstance()
		        .get(initMasterConfig()).getDatabaseName();
		GenericApplication.getInstance().getApplicationContext()
		        .deleteDatabase(databaseName);
		final String extStorageDirectory = Environment
		        .getExternalStorageDirectory().toString();
		final String applicationName = GenericApplication.getInstance()
		        .getApplicationName();
		final File file = new File(extStorageDirectory + "/" + applicationName);
		deleteDirectory(file);
		GenericSharePreference.getInstance().clearSharePreference();
		final Context context = genericFragment.getApplicationContext();
		final PackageManager packageManager = context.getPackageManager();
		final Intent intent = packageManager.getLaunchIntentForPackage(context
		        .getPackageName());
		intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		genericFragment.startActivity(intent);
		FormDesignManager.getInstance().clearCache();
		ContentDataManager.getInstance().clearCache();
	}
}
